package sky.dao.Impl;

import org.hibernate.Hibernate;
import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.hibernate.type.Type;
import org.omg.Dynamic.Parameter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import sky.dao.FlightDAO;
import sky.domain.Airport;
import sky.domain.Flight;
import sky.domain.Plane;
import sky.exceptions.bookTicketException;
import sky.tro.ParameterAndCriteria;
import sky.tro.TicketFinder;

import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * Created with IntelliJ IDEA.
 * User: Gauss
 * Date: 24.04.13
 * Time: 17:10
 * To change this template use File | Settings | File Templates.
 */
@Repository
public class FlightDAOImpl implements FlightDAO {

    @Autowired
    private SessionFactory sessionFactory;

    @Override
    public void addFlight(Flight flight) {
        Query query = sessionFactory.getCurrentSession().createQuery("from Airport where name = ?");
        query.setParameter(0, flight.getDepartureAirport().getName(), Hibernate.STRING);
        flight.setDepartureAirport((Airport) query.uniqueResult());
        query = sessionFactory.getCurrentSession().createQuery("from Airport where name = ?");
        query.setParameter(0, flight.getDestinationAirport().getName(), Hibernate.STRING);
        flight.setDestinationAirport((Airport) query.uniqueResult());
        query = sessionFactory.getCurrentSession().createQuery("from Plane where name = ?");
        query.setParameter(0, flight.getPlane().getName(), Hibernate.STRING);
        Plane plane = (Plane) query.uniqueResult();
        flight.setFreeEconomPlaces(plane.getEconomPlaces());
        flight.setFreeBussinessPlaces(plane.getBussinessPlaces());
        flight.setFreeFirstClassPlaces(plane.getFirstClassPlaces());
        flight.setFreeAllPlaces(plane.getAllPlaces());
        flight.setPlane(plane);
        sessionFactory.getCurrentSession().save(flight);
    }

    @Override
    @SuppressWarnings("unchecked")
    public List<Flight> listFlight() {
        return sessionFactory.getCurrentSession().createQuery("from Flight").list();
    }

    @Override
    @SuppressWarnings("unchecked")
    public List<Flight> sortingList(String sortParam) {
        if ("departureAirport".equals(sortParam)) sortParam="departureAirport.name";
        if ("destinationAirport".equals(sortParam)) sortParam="destinationAirport.name";
        if ("depCity".equals(sortParam)) sortParam="departureAirport.city.name";
        if ("desCity".equals(sortParam)) sortParam="destinationAirport.city.name";
        if ("depDate".equals(sortParam)) sortParam="departureDate";
        if ("desDate".equals(sortParam)) sortParam="destinationDate";
        return sessionFactory.getCurrentSession().createQuery("from Flight as flight order by flight."+sortParam).list();
    }

    @Override
    public void removeFlight(Integer id) {
        Flight flight = (Flight) sessionFactory.getCurrentSession().load(Flight.class, id);
        if (null != flight) {
            sessionFactory.getCurrentSession().delete(flight);
        }
    }

    @Override
    @SuppressWarnings("unchecked")
    public List<Flight> findByFinder(TicketFinder finder, String sortStr, String ticketType) {
        List<ParameterAndCriteria> list = finder.getCriteriaList();
        StringBuilder builder = new StringBuilder("from Flight as flight where ");
        for (ParameterAndCriteria entry : list) {
            builder.append("flight.");
            builder.append(entry.getParamName());
            builder.append(transformToCriteria(entry.getSymbol()));
            builder.append("? and ");
        }
        builder.delete(builder.length()-5, builder.length());
        builder.append(" order by flight.");
        if ("departureAirport".equals(sortStr)) sortStr="departureAirport.name";
        if ("destinationAirport".equals(sortStr)) sortStr="destinationAirport.name";
        if ("depCity".equals(sortStr)) sortStr="departureAirport.city.name";
        if ("desCity".equals(sortStr)) sortStr="destinationAirport.city.name";
        if ("depDate".equals(sortStr)) sortStr="departureDate";
        if ("desDate".equals(sortStr)) sortStr="destinationDate";
        if ("price".equals(sortStr)) sortStr=ticketType.replaceFirst("[A-Z]{1}",ticketType.substring(0,1).toLowerCase())+"Cost";
        builder.append(sortStr);
        Query query = sessionFactory.getCurrentSession().createQuery(builder.toString());
        int i = 0;
        for (ParameterAndCriteria entry: list) {
            query.setParameter(i, entry.getParamValue(), entry.getHibernateType());
            i++;
        }
        return query.list();
    }

    @Override
    public void editFlight(Flight flight) {
        Query query = sessionFactory.getCurrentSession().createQuery("from Airport where name = ?");
        query.setParameter(0, flight.getDepartureAirport().getName(), Hibernate.STRING);
        flight.setDepartureAirport((Airport) query.uniqueResult());
        query = sessionFactory.getCurrentSession().createQuery("from Airport where name = ?");
        query.setParameter(0, flight.getDestinationAirport().getName(), Hibernate.STRING);
        flight.setDestinationAirport((Airport) query.uniqueResult());
        query = sessionFactory.getCurrentSession().createQuery("from Plane where name = ?");
        query.setParameter(0, flight.getPlane().getName(), Hibernate.STRING);
        flight.setPlane((Plane) query.uniqueResult());
        sessionFactory.getCurrentSession().update(flight);
    }

    @Override
    public void bookTickets(Integer id, Integer numberOfTickets, String ticketType) {
        Flight flight = (Flight) sessionFactory.getCurrentSession().load(Flight.class, id);
        if ("Econom".equals(ticketType)) {
            flight.setFreeEconomPlaces(flight.getFreeEconomPlaces()-numberOfTickets);
        }
        if ("Bussiness".equals(ticketType)) {
            flight.setFreeBussinessPlaces(flight.getFreeBussinessPlaces()-numberOfTickets);
        }
        if ("FirstClass".equals(ticketType)) {
            flight.setFreeFirstClassPlaces(flight.getFreeFirstClassPlaces()-numberOfTickets);
        }
        flight.setFreeAllPlaces(flight.getFreeAllPlaces()-numberOfTickets);
        sessionFactory.getCurrentSession().update(flight);
    }

    @Override
    public Flight getFlightById(Integer id) {
        return (Flight) sessionFactory.getCurrentSession().get(Flight.class, id);
    }

    private String transformToCriteria(Integer criteria) {
        switch (criteria) {
            case 1: return " <= ";
            case 2: return " >= ";
            default: return " = ";
        }
    }

}
